<?php
//writeCData

class Eml {

	private $na = "N/A";
	
	public function __construct() {
		$this->errorTypes[1] = "Required field not provided.";
		$this->errorTypes[2] = "Not valid type found.";
		$this->errorTypes[3] = "Please ensure all four bounding box values are complete and in the proper range.";
		$this->errorTypes[4] = "Longitude must be between �180.";
		$this->errorTypes[5] = "Latitude must be between �90.";
		$this->errorTypes[6] = "Precision required at least 2 deciaml places.";
		$this->errorTypes[7] = "Please make sure web addresses start with �http://�.";
		$this->errors = array();
	}
	
	public function set( $name, $value ) {
		$this->data[$name] = $value;
	}

	public function get( $name ) {
		return( $this->data[$name] );
	}

	private function addCreator() {
		# The creator is the person who created the resource (not necessarily the author of this metadata about the resource)
		#	COLUMN C IN THE SPREADSHEET
		$this->xml->startElement('creator');
			$this->xml->startElement('individualName');
				$this->xml->startElement('givenName');
					# Requires at least 1 char
					$this->xml->text( ($this->get('ResourceCreator.FirstName') == "") ? $this->na : $this->get('ResourceCreator.FirstName') );
				$this->xml->endElement();
				$this->xml->startElement('surName');
					# Requires at least 1 char
					$this->xml->text( ($this->get('ResourceCreator.LastName') == "") ? $this->na : $this->get('ResourceCreator.LastName') );
				$this->xml->endElement();
			$this->xml->endElement();
			$this->xml->startElement('organizationName');
				# Requires at least 1 char
				$this->xml->text( ($this->get('ResourceCreator.Organisation') == "") ? $this->na : $this->get('ResourceCreator.Organisation') );
			$this->xml->endElement();
			if ($this->get('ResourceCreator.PositionName') != "") {				
			$this->xml->startElement('positionName');
				# REQUIRED to have a valid string
				$this->xml->text( ($this->get('ResourceCreator.PositionName') == "") ? $this->na : $this->get('ResourceCreator.PositionName') );
			$this->xml->endElement();
			}
			$this->xml->startElement('address');
				if ($this->get('ResourceCreator.Address') != "") {				
				$this->xml->startElement('deliveryPoint');
					# Requires at least 1 char
					$this->xml->text( ($this->get('ResourceCreator.Address') == "") ? $this->na : $this->get('ResourceCreator.Address') );
				$this->xml->endElement();
				}
				if ($this->get('ResourceCreator.City') != "") {				
				$this->xml->startElement('city');
					# Requires at least 1 char
					$this->xml->text( ($this->get('ResourceCreator.City') == "") ? $this->na : $this->get('ResourceCreator.City') );
				$this->xml->endElement();
				}
				if ($this->get('ResourceCreator.Province') != "") {				
				$this->xml->startElement('administrativeArea');
					# Requires at least 1 char
					$this->xml->text( ($this->get('ResourceCreator.Province') == "") ? $this->na : $this->get('ResourceCreator.Province') );
				$this->xml->endElement();
				}
				if ($this->get('ResourceCreator.PostalCode') != "") {				
				$this->xml->startElement('postalCode');
					# Requires at least 1 char
					$this->xml->text( ($this->get('ResourceCreator.PostalCode') == "") ? $this->na : $this->get('ResourceCreator.PostalCode') );
				$this->xml->endElement();
				}
				if ($this->get('ResourceCreator.Country') != "") {
				$this->xml->startElement('country');
					# Requires at least 1 char
					$this->xml->text( ($this->get('ResourceCreator.Country') == "") ? $this->na : $this->get('ResourceCreator.Country') );
				$this->xml->endElement();
				}
			$this->xml->endElement();
			if ($this->get('ResourceCreator.Phone') != "") {				
			$this->xml->startElement('phone');
				$this->xml->text( $this->get('ResourceCreator.Phone') );
			$this->xml->endElement();
			}
			if ($this->get('ResourceCreator.Email') != "") {				
			$this->xml->startElement('electronicMailAddress');
				# Requires at least 1 char
				$this->xml->text( ($this->get('ResourceCreator.Email') == "") ? $this->na : $this->get('ResourceCreator.Email') );
			$this->xml->endElement();
			}
			if ($this->get('ResourceCreator.Homepage') != "") {				
			$this->xml->startElement('onlineUrl');
				$this->xml->text( $this->get('ResourceCreator.Homepage') );
			$this->xml->endElement();
			}
		$this->xml->endElement(); // creator		
	}
	
	private function addMetaProvider() {
		# The responsible party for the creation of the metadata
		# COLUMN B IN THE SPREADSHEET
		$this->xml->startElement('metadataProvider');
			$this->xml->startElement('organizationName');
				$this->xml->text( ($this->get('MetadataAuthor.Organisation') == "") ? $this->na : $this->get('MetadataAuthor.Organisation') );
			$this->xml->endElement();
			$this->xml->startElement('individualName');
				$this->xml->startElement('givenName');
					# Requires at least 1 char
					$this->xml->text( ($this->get('MetadataAuthor.FirstName') == "") ? $this->na : $this->get('MetadataAuthor.FirstName') );
				$this->xml->endElement();
				$this->xml->startElement('surName');
					$this->xml->text( ($this->get('MetadataAuthor.LastName') == "") ? $this->na : $this->get('MetadataAuthor.LastName') );
				$this->xml->endElement();
			$this->xml->endElement();
			if ($this->get('MetadataAuthor.PositionName') != "") {				
			$this->xml->startElement('positionName');
				# REQUIRED to have a valid string
				$this->xml->text( ($this->get('MetadataAuthor.PositionName') == "") ? $this->na : $this->get('MetadataAuthor.PositionName') );
			$this->xml->endElement();
			}
			$this->xml->startElement('address');
				if ($this->get('MetadataAuthor.Address') != "") {				
				$this->xml->startElement('deliveryPoint');
					$this->xml->text( ($this->get('MetadataAuthor.Address') == "") ? $this->na : $this->get('MetadataAuthor.Address') );
				$this->xml->endElement();
				}
				if ($this->get('MetadataAuthor.City') != "") {				
				$this->xml->startElement('city');
					$this->xml->text( ($this->get('MetadataAuthor.City') == "") ? $this->na : $this->get('MetadataAuthor.City') );
				$this->xml->endElement();
				}
				if ($this->get('MetadataAuthor.Province') != "") {				
				$this->xml->startElement('administrativeArea');
					$this->xml->text( ($this->get('MetadataAuthor.Province') == "") ? $this->na : $this->get('MetadataAuthor.Province') );
				$this->xml->endElement();
				}
				if ($this->get('MetadataAuthor.PostalCode') != "") {				
				$this->xml->startElement('postalCode');
					$this->xml->text( ($this->get('MetadataAuthor.PostalCode') == "") ? $this->na : $this->get('MetadataAuthor.PostalCode') );
				$this->xml->endElement();
				}	
				if ($this->get('MetadataAuthor.Country') != "") {				
				$this->xml->startElement('country');
					$this->xml->text( ($this->get('MetadataAuthor.Country') == "") ? $this->na : $this->get('MetadataAuthor.Country') );
				$this->xml->endElement();
				}
			$this->xml->endElement(); // address
			if ($this->get('MetadataAuthor.Phone') != "") {				
			$this->xml->startElement('phone');
				$this->xml->text( $this->get('MetadataAuthor.Phone') );
			$this->xml->endElement();
			}
			if ($this->get('MetadataAuthor.Email') != "") {							
			$this->xml->startElement('electronicMailAddress');
				$this->xml->text( ($this->get('MetadataAuthor.Email') == "") ? $this->na : $this->get('MetadataAuthor.Email') );
			$this->xml->endElement();
			}
			if ($this->get('MetadataAuthor.Homepage') != "") {				
			$this->xml->startElement('onlineUrl');
				$this->xml->text( $this->get('MetadataAuthor.Homepage') );
			$this->xml->endElement();
			}
		$this->xml->endElement(); // metaProvider
	}
	
	private function addAssociatedParty( $party ) {
		# Note that associated parties have roles
		# COLUMN D IN THE SPREADSHEET
		$this->xml->startElement('associatedParty');
			$this->xml->startElement('individualName');
				$this->xml->startElement('givenName');
					# Requires at least 1 char
					$this->xml->text( ($party['FirstName'] == "") ? $this->na : $party['FirstName'] );
				$this->xml->endElement();
				$this->xml->startElement('surName');
					$this->xml->text( ($party['LastName'] == "") ? $this->na : $party['LastName'] );
				$this->xml->endElement();
			$this->xml->endElement();
			$this->xml->startElement('organizationName');
				$this->xml->text( ($party['Organisation'] == "") ? $this->na : $party['Organisation'] );
			$this->xml->endElement();
			if ($party['PositionName'] != "") {							
			$this->xml->startElement('positionName');
				# REQUIRED to have a valid string
				$this->xml->text( ($party['PositionName'] == "") ? $this->na : $party['PositionName'] );
			$this->xml->endElement();
			}
			$this->xml->startElement('address');
				if ($party['Address'] != "") {							
				$this->xml->startElement('deliveryPoint');
					$this->xml->text( ($party['Address'] == "") ? $this->na : $party['Address'] );
				$this->xml->endElement();
				}
				if ($party['City'] != "") {										
				$this->xml->startElement('city');
					$this->xml->text( ($party['City'] == "") ? $this->na : $party['City'] );
				$this->xml->endElement();
				}
				if ($party['Province'] != "") {										
				$this->xml->startElement('administrativeArea');
					$this->xml->text( ($party['Province'] == "") ? $this->na : $party['Province'] );
				$this->xml->endElement();
				}
				if ($party['PostalCode'] != "") {							
				$this->xml->startElement('postalCode');
					$this->xml->text( ($party['PostalCode'] == "") ? $this->na : $party['PostalCode'] );
				$this->xml->endElement();
				}
				if ($party['Country'] != "") {							
				$this->xml->startElement('country');
					$this->xml->text( ($party['Country'] == "") ? $this->na : $party['Country'] );
				$this->xml->endElement();
				}
			$this->xml->endElement(); // address
			if ($party['Phone'] != "") {							
			$this->xml->startElement('phone');
				$this->xml->text($party['Phone'] );
			$this->xml->endElement();
			}
			if ($party['Email'] != "") {							
			$this->xml->startElement('electronicMailAddress');
				$this->xml->text( ($party['Email'] == "") ? $this->na : $party['Email'] );
			$this->xml->endElement();
			}
			if ($party['Homepage'] != "") {							
			$this->xml->startElement('onlineUrl');
				$this->xml->text( $party['Homepage'] );
			$this->xml->endElement();
			}
			# The IPT will define a controlled vocabulary for this term
			$this->xml->startElement('role');
				# Requires at least 1 char
				$this->xml->text( ($party['Role'] == "") ? $this->na : $party['Role'] );
			$this->xml->endElement();
		$this->xml->endElement(); // associatedParty
		
	}
	
	private function addKeywords() {
		#	Keywords can optionally reference a thesaurus
		$this->xml->startElement('keywordSet');
			$keywords = $this->get('KeyWords');
			if(is_array($keywords) && count($keywords)) {
				foreach($keywords as $keyword) {
					$this->xml->startElement('keyword');
						$this->xml->text(trim($keyword));
					$this->xml->endElement();
				}
			}
			$this->xml->startElement('keywordThesaurus');
				$this->xml->text( ($this->get('KeywordThesaurus') == "") ? $this->na : $this->get('KeywordThesaurus') );
			$this->xml->endElement();
			$this->xml->startElement('taxonomicKeywords');
				$this->xml->text( ($this->get('taxonomicKeywords') == "") ? $this->na : $this->get('taxonomicKeywords') );
			$this->xml->endElement();
		$this->xml->endElement();
	}

	private function addCoverage() {
		$this->xml->startElement('coverage');
			#	PROCESSOR The geographic description refers to bounding box - Is BBOX REQUIRED-->
			$this->xml->startElement('geographicCoverage');
				$this->xml->startElement('geographicDescription');
					$this->xml->text( $this->get('RegionalScope') );
				$this->xml->endElement();
				$this->xml->startElement('boundingCoordinates');
				$this->xml->startElement('westBoundingCoordinate');
					$this->xml->text( $this->get('BoundingBoxLeftLong') );
				$this->xml->endElement();
				$this->xml->startElement('eastBoundingCoordinate');
					$this->xml->text( $this->get('BoundingBoxRightLong') );
				$this->xml->endElement();
				$this->xml->startElement('northBoundingCoordinate');
					$this->xml->text( $this->get('BoundingBoxLeftLat') );
				$this->xml->endElement();
				$this->xml->startElement('southBoundingCoordinate');
					$this->xml->text( $this->get('BoundingBoxRightLat') );
				$this->xml->endElement();
				$this->xml->endElement(); // boundingCoordinates
			$this->xml->endElement(); // geographicCoverage
	
			#	PROCESSOR ELSE IF ONLY BEGIN DATE singleDateTime
			$this->xml->startElement('temporalCoverage');
				$this->xml->startElement('singleDateTime');
					$this->xml->startElement('calendarDate');
						$this->xml->text( $this->get('BeginDateorSingleDate') );
					$this->xml->endElement();
				$this->xml->endElement();
			$this->xml->endElement(); // temporalCoverage

			#	PROCESSOR IF BOTH BEGIN DATE AND END DATE WE OUTPUT rangeOfDates
			$this->xml->startElement('temporalCoverage');
				$this->xml->startElement('rangeOfDates');
					$this->xml->startElement('beginDate');
						$this->xml->startElement('calendarDate');
							$this->xml->text( $this->get('BeginDateorSingleDate') );
						$this->xml->endElement();
					$this->xml->endElement();
					$this->xml->startElement('endDate');
						$this->xml->startElement('calendarDate');
							$this->xml->text( $this->get('EndDate') );
						$this->xml->endElement();
					$this->xml->endElement();
				$this->xml->endElement();
			$this->xml->endElement(); // temporalCoverage
/*
			$this->xml->startElement('taxonomicCoverage');
				$this->xml->startElement('generalTaxonomicCoverage');
				$this->xml->endElement();
			$this->xml->endElement();
*/
		$this->xml->endElement(); // End Coverage		
	}
	
	private function addProject() {
		#PROCESSOR SEE RESEARCH PROJECT SECTION IN SPREADSHEET
		$this->xml->startElement('project');
			$this->xml->startElement('title');
				$this->xml->text( ($this->get('ProjectTitle') == '') ? $this->na : $this->get('ProjectTitle') );
			$this->xml->endElement();
			$this->xml->startElement('personnel');
// Removed according to discussion with David, Tim on 26 Apr 11
//				$this->xml->startElement('organizationName');
//					$this->xml->text( ($this->get('ProjectLeadOrganisation') == '') ? $this->na : $this->get('ProjectLeadOrganisation') );
//				$this->xml->endElement();
			$this->xml->startElement('individualName');
				$this->xml->startElement('givenName');
					$this->xml->text( ($this->get('ResourceCreator.FirstName') == "") ? $this->na : $this->get('ResourceCreator.FirstName') );
				$this->xml->endElement();
				$this->xml->startElement('surName');
					$this->xml->text( ($this->get('ResourceCreator.LastName') == "") ? $this->na : $this->get('ResourceCreator.LastName') );
				$this->xml->endElement();
			$this->xml->endElement();
				$this->xml->startElement('role');
					$this->xml->text("pointOfContact");
				$this->xml->endElement();
			$this->xml->endElement(); # personnel
			$this->xml->startElement('funding');
				$this->xml->startElement('para');
				$this->xml->endElement();
			$this->xml->endElement();
			$this->xml->startElement('studyAreaDescription');
				$this->xml->startElement('descriptor');
					$this->xml->writeAttribute('name', 'generic');
					$this->xml->writeAttribute('citableClassificationSystem', 'false');
					$this->xml->startElement('descriptorValue');
					$this->xml->endElement();
				$this->xml->endElement();
			$this->xml->endElement();

//			if ($this->get('ProjectDescription') != "") {
			$this->xml->startElement('designDescription');
				$this->xml->startElement('description');
					$this->xml->startElement('para');
						$this->xml->text( $this->get('ProjectDescription') );
					$this->xml->endElement();
				$this->xml->endElement();
			$this->xml->endElement();
//			}
		$this->xml->endElement(); # project
	}
	
	private function addContact() {
		#	This is mandatory in EML
		#	In terms of the IPT, propose this be the same as the and should be the same as the <creator/> 
		#	Therefore, it can be ignored in Parsing, but needs to be created in the output rendering
		#	PROCESSOR ONE OF THE AGENTS IN PEOPLE AND ORGANISATIONS SELECT BASED ON
		$this->xml->startElement('contact');
			$this->xml->startElement('individualName');
				$this->xml->startElement('givenName');
				$this->xml->text($this->get('ResourceCreator.FirstName'));
				$this->xml->endElement();
				$this->xml->startElement('surName');
				$this->xml->text($this->get('ResourceCreator.LastName'));
				$this->xml->endElement();
			$this->xml->endElement();
			$this->xml->startElement('organizationName');
			$this->xml->text($this->get('ResourceCreator.Organisation'));
			$this->xml->endElement();
			if ($this->get('ResourceCreator.PositionName') != "") {				
			$this->xml->startElement('positionName');
				$this->xml->text( ($this->get('ResourceCreator.PositionName') == "") ? $this->na : $this->get('ResourceCreator.PositionName') );
			$this->xml->endElement();
			}
			$this->xml->startElement('address');
				if ($this->get('ResourceCreator.Address') != "") {				
				$this->xml->startElement('deliveryPoint');
					# Requires at least 1 char
					$this->xml->text( ($this->get('ResourceCreator.Address') == "") ? $this->na : $this->get('ResourceCreator.Address') );
				$this->xml->endElement();
				}
				if ($this->get('ResourceCreator.City') != "") {								
				$this->xml->startElement('city');
					# Requires at least 1 char
					$this->xml->text( ($this->get('ResourceCreator.City') == "") ? $this->na : $this->get('ResourceCreator.City') );
				$this->xml->endElement();
				}
				if ($this->get('ResourceCreator.Province') != "") {
				$this->xml->startElement('administrativeArea');
					# Requires at least 1 char
					$this->xml->text( ($this->get('ResourceCreator.Province') == "") ? $this->na : $this->get('ResourceCreator.Province') );
				$this->xml->endElement();
				}
				if ($this->get('ResourceCreator.PostalCode') != "") {
				$this->xml->startElement('postalCode');
					# Requires at least 1 char
					$this->xml->text( ($this->get('ResourceCreator.PostalCode') == "") ? $this->na : $this->get('ResourceCreator.PostalCode') );
				$this->xml->endElement();
				}
				if ($this->get('ResourceCreator.Country') != "") {
				$this->xml->startElement('country');
					# Requires at least 1 char
					$this->xml->text( ($this->get('ResourceCreator.Country') == "") ? $this->na : $this->get('ResourceCreator.Country') );
				$this->xml->endElement();
				}
			$this->xml->endElement();
			if ($this->get('ResourceCreator.Phone') != "") {
			$this->xml->startElement('phone');
				$this->xml->text( $this->get('ResourceCreator.Phone') );
			$this->xml->endElement();
			}
			if ($this->get('ResourceCreator.Email') != "") {
			$this->xml->startElement('electronicMailAddress');
				# Requires at least 1 char
				$this->xml->text( ($this->get('ResourceCreator.Email') == "") ? $this->na : $this->get('ResourceCreator.Email') );
			$this->xml->endElement();
			}
			if ($this->get('ResourceCreator.Homepage') != "") {
			$this->xml->startElement('onlineUrl');
				$this->xml->text( $this->get('ResourceCreator.Homepage') );
			$this->xml->endElement();
			}
		$this->xml->endElement();
	}
	
	public function generateXml( $header = 1, $url = '', $label = '' ) {
		$this->url = ($url == '') ? "http://" . $_SERVER['HTTP_HOST'] . "/" : $url;
		if ($header) {
			header("content-type: text/xml");
		}

		$this->xml = new XMLWriter();
		$this->xml->openMemory();
		$this->xml->startDocument('1.0', 'UTF-8');
		$this->xml->setIndent(4);
			$this->xml->startElement('eml:eml');

			$this->xml->writeAttribute('xmlns:eml', 'eml://ecoinformatics.org/eml-2.1.1');
			$this->xml->writeAttribute('xmlns:md', 'eml://ecoinformatics.org/methods-2.1.1');
			$this->xml->writeAttribute('xmlns:proj', 'eml://ecoinformatics.org/project-2.1.1');
			$this->xml->writeAttribute('xmlns:d', 'eml://ecoinformatics.org/dataset-2.1.1');
			$this->xml->writeAttribute('xmlns:res', 'eml://ecoinformatics.org/resource-2.1.1');
			$this->xml->writeAttribute('xmlns:dc', 'http://purl.org/dc/terms/');
			$this->xml->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
			$this->xml->writeAttribute('xsi:schemaLocation', 'eml://ecoinformatics.org/eml-2.1.1 http://rs.gbif.org/schema/eml-gbif-profile/1.0/eml.xsd');
			$this->xml->writeAttribute('packageId', ($this->get('ResourceUUID') == "") ? "" : $this->get('ResourceUUID') );
			$this->xml->writeAttribute('system', 'GBIF-SpreadsheetProcessor');
			$this->xml->writeAttribute('scope', 'system');
//			$this->xml->writeAttribute('xml:lang', ($this->get('MetadataLanguage') == "") ? "en" : $this->get('MetadataLanguage') ); 			
			$this->xml->writeAttribute('xml:lang', $this->get('MetadataLanguage') ); 			
			# Dataset
				$this->xml->startElement('dataset');
					# PROCESSOR generates a UUID for uniquely identifying each resource
					$this->xml->startElement('alternateIdentifier');
					$this->xml->endElement();
					$this->xml->startElement('title');
					$this->xml->writeAttribute('xml:lang','eng');
					# Requires at least 1 char
					$this->xml->text( ($this->get('ResourceTitle') == "") ? $this->na : $this->get('ResourceTitle') );
					$this->xml->endElement();
					
					$this->addCreator();
					$this->addMetaProvider();

					$authors = $this->get("authors");
					if(is_array($authors) && count($authors)) {
					foreach($authors as $author) {						
						$this->addAssociatedParty($author);
					}
					}
		
					// If there is a Lead Organisation, add on associatedParty with role "distributor"
					// Burke@GBIFS 28 Apr 2011f
					if ($this->get('ProjectLeadOrganisation') != "") {
						$this->xml->startElement('associatedParty');
							$this->xml->startElement('organizationName');
								$this->xml->text( $this->get('ProjectLeadOrganisation') );
							$this->xml->endElement();
							// If country is specified, add address element
							if ($this->get('ProjectLeadOrganisationCountry') != "" ) {
								$this->xml->startElement('address');
									$this->xml->startElement('country');
										$this->xml->text( $this->get('ProjectLeadOrganisationCountry') );
									$this->xml->endElement();
								$this->xml->endElement();
							}
							$this->xml->startElement('role');
								$this->xml->text('distributor');
							$this->xml->endElement();
						$this->xml->endElement();
					}
		
					# Identified in the Other section of the GBIF Extended Metadata Doc
					# PROESSOR DATA SET CAPTURE DATE
					$this->xml->startElement('pubDate');
						$this->xml->text( $this->get('ResourcePublicationDate') );
					$this->xml->endElement();

					# Identified in the Other section of the GBIF Extended Metadata Doc
					# This is the RESOURCE language and not the metadata language which is at the bottom
					# CELL B5
					$this->xml->startElement('language');
						$this->xml->text( ($this->get('ResourceLanguage') == '') ? 'eng' : $this->get('ResourceLanguage') );
					$this->xml->endElement();

					#	The brief overview
					#	CELL B10 PROCESSOR WILL SPLIT BY NEWLINE INTO PARA TAGS					
					$this->xml->startElement('abstract');
						$this->xml->startElement('para');
							$this->xml->text( $this->get('ResourceAbstract') );
						$this->xml->endElement();
					$this->xml->endElement();

					if ( ($this->get('KeyWords') != "") || ($this->get('KeywordThesaurus') != "") || ($this->get('taxonomicKeywords') != "") ){
						$this->addKeywords();
					}

					#	Not mentioned in the GBIF Extended Metadata Doc but seems sensible to keep this element
					$this->xml->startElement('additionalInfo');
						$this->xml->startElement('para');
							$this->xml->text( $this->get('ResourceAdditionalInformation') );						
						$this->xml->endElement();
					$this->xml->endElement();

					if ($this->get('ResourceCreativeCommonsLicensing') != "") {
					#	Identified in the Other section of the GBIF Extended Metadata Doc -->
					$this->xml->startElement('intellectualRights');
						$this->xml->startElement('para');
							$this->xml->text( $this->get('ResourceCreativeCommonsLicensing') );
						$this->xml->endElement();
					$this->xml->endElement();
					}

					if ($this->get('ResourceURL') != "") {
					$this->xml->startElement('distribution');
						$this->xml->writeAttribute('scope', 'document');
						$this->xml->startElement('online');
							$this->xml->startElement('url');
								$this->xml->writeAttribute('function', 'information');
								$this->xml->text( $this->get('ResourceURL') );
							$this->xml->endElement();
						$this->xml->endElement();
					$this->xml->endElement();
					}

					$this->addCoverage();
					$this->addContact();

				if ( ($this->get('ProjectTitle') != "") || ($this->get('ProjectLeadOrganisation') != "") || ($this->get('ProjectDescription') != "")) {
					$this->addProject();
				}

			$this->xml->endElement(); # End Dataset

			$this->xml->startElement('additionalMetadata');
				$this->xml->startElement('metadata');
					$this->xml->startElement('gbif');

						$this->xml->startElement('dateStamp');
							$this->xml->text( date("c") );
						$this->xml->endElement(); # startDate

/*
						$this->xml->startElement('hierarchyLevel');
						$this->xml->endElement(); # 
*/						
						$this->xml->startElement('citation');
							$this->xml->text( $this->get('ResourceExpectedCitation') );						
						$this->xml->endElement(); # 

						$references = $this->get('references');
						if (!empty($references)) {
							$this->xml->startElement('bibliography');
								$references = $this->get('references');
								if(is_array($references) && count($references)) {
									foreach($references as $reference) {
										$this->xml->startElement('citation');
											$this->xml->text( $reference );
										$this->xml->endElement();
									}
								}
							$this->xml->endElement(); # bibliography
						}

						if (($this->get('CollectionName') != '')
						|| ($this->get('CollectionIdentifier') != '')														
						|| ($this->get('ParentCollectionIdentifier') != '') ){
							$this->xml->startElement('collection');

								if ($this->get('ParentCollectionIdentifier') != '') {
									$this->xml->startElement('parentCollectionIdentifier');
										$this->xml->text( $this->get('ParentCollectionIdentifier') );
									$this->xml->endElement(); # ParentCollectionIdentifier
								}

								if ($this->get('CollectionIdentifier') != '') {
									$this->xml->startElement('collectionIdentifier');
										$this->xml->text( $this->get('CollectionIdentifier') );
									$this->xml->endElement(); # CollectionIdentifier
								}

								if ($this->get('CollectionName') != '') {
									$this->xml->startElement('collectionName');
										$this->xml->text( $this->get('CollectionName') );
									$this->xml->endElement(); # CollectionName
								}

							$this->xml->endElement(); # collection
						}

						if ($this->get('FormationPeriod') != '') {
							$this->xml->startElement('formationPeriod');
								$this->xml->text( $this->get('FormationPeriod') );
							$this->xml->endElement(); # FormationPeriod
						}

						if ($this->get('SpecimenPreservationMethod') != '') {
							$this->xml->startElement('specimenPreservationMethod');
								$this->xml->text( $this->get('SpecimenPreservationMethod') );
							$this->xml->endElement(); # SpecimenPreservationMethod
						}

						if ($this->get('LivingTimePeriod') != '') {
							$this->xml->startElement('livingTimePeriod');
								$this->xml->text( $this->get('LivingTimePeriod') );
							$this->xml->endElement(); # LivingTimePeriod
						}

/*
							$this->xml->startElement('physical');
								$this->xml->startElement('objectName');
	
								$this->xml->endElement();
								$this->xml->startElement('characterEncoding');
	
								$this->xml->endElement();
								$this->xml->startElement('dataFormat');
									$this->xml->startElement('externallyDefinedFormat');
										$this->xml->startElement('formatName');
										$this->xml->endElement();
										$this->xml->startElement('formatVersion');
										$this->xml->endElement();
									$this->xml->endElement();
								$this->xml->endElement(); # dataFormat
	
							$this->xml->endElement(); # physical
	
							$this->xml->startElement('collection');
								$this->xml->startElement('parentCollectionIdentifier');
	
								$this->xml->endElement();
								$this->xml->startElement('collectionIdentifier');
	
								$this->xml->endElement();
								$this->xml->startElement('collectionName');
	
								$this->xml->endElement();
							$this->xml->endElement(); # collection
	
	
							$this->xml->startElement('jgtiCuratorialUnit');
								$this->xml->startElement('jgtiUnitType');
	
								$this->xml->endElement();
								$this->xml->startElement('jgtiUnitRange');
									$this->xml->startElement('beginRange');
		
									$this->xml->endElement();
									$this->xml->startElement('endRange');
		
									$this->xml->endElement();
								$this->xml->endElement(); # jgtiUnitRange
							$this->xml->endElement(); # jgtiCuratorialUnit
*/
						$this->xml->endElement(); # gif
					$this->xml->endElement(); # metadata
				$this->xml->endElement(); # additionalMetadata

			$this->xml->endElement(); # eml
		$this->xml->endDocument();
	}

	public function getIssues() {
		return( array("errors" => $this->errors, "warnings" => $this->warnings) );
	}

	private function addError($key, $value, $type) {
		$errorMsg = $this->errorTypes[$type];
		$tmp = array("variable" => $key, "value" =>  $value, "type" => $type, "msg" => $errorMsg );
		array_push($this->errors, $tmp);
		$this->error = true;
	}
	
	private function addWarning($key, $value, $type) {
		$errorMsg = $this->errorTypes[$type];
		$tmp = array("variable" => $key, "value" =>  $value, "type" => $type, "msg" => $errorMsg );
		$this->warnings[] = array($tmp);
		$this->error = true;
	}

	private function checkRequired($key) {
		if ($this->data[$key] == "") {
			$this->addError($key, $this->data[$key], 1);
		}
	}
	
	public function hasErrors() {
		return( $this->error );
	}
	
	private function getDecLen( $dec ) {
		$pieces = explode(".", $dec);
		return(strlen($pieces[1]));
	}
	public function validate() {
		$this->error = false;
		# Check Required Fields
		$this->checkRequired("ResourceTitle");
		$this->checkRequired("ResourcePublicationDate");
		$this->checkRequired("ResourceExpectedCitation");
		$this->checkRequired("ResourceAbstract");
		$this->checkRequired("ResourceCreator.FirstName");
		$this->checkRequired("ResourceCreator.LastName");
		$this->checkRequired("ResourceCreator.Organisation");
		$this->checkRequired("MetadataAuthor.FirstName");
		$this->checkRequired("MetadataAuthor.LastName");
		$this->checkRequired("MetadataAuthor.Organisation");

		if (count($this->data["authors"])) {
		foreach($this->data["authors"] as $author) {
			if ($author["FirstName"] == "") {
				$this->addError("FirstName", "", 1);
			}
			if ($author["LastName"] == "") {
				$this->addError("LastName", "", 1);
			}
			if ($author["Organisation"] == "") {
				$this->addError("Organisation", "", 1);
			}			
		}
		}
		
		if (
					($this->data['BoundingBoxLeftLat'] != "")
			||	($this->data['BoundingBoxLeftLong'] != "")
			||	($this->data['BoundingBoxRightLat'] != "")
			||	($this->data['BoundingBoxRightLong'] != "")
		) {
			// Test it all values are suplied
			if (
						($this->data['BoundingBoxLeftLat'] == "")
				||	($this->data['BoundingBoxLeftLong'] == "")
				||	($this->data['BoundingBoxRightLat'] == "")
				||	($this->data['BoundingBoxRightLong'] == "")
			) {
				$this->addWarning("BoundingBox", "", 3);
			} else {
					// Check -180 to 180
					if (
								( ($this->data['BoundingBoxRightLong'] > 180) && ($this->data['BoundingBoxRightLong'] < -180) )
						||	( ($this->data['BoundingBoxLeftLong'] > 180) && ($this->data['BoundingBoxLeftLong'] < -180) )
					) {
						$this->addWarning("BoundingBoxLong", $this->data['BoundingBoxRightLong'] . " " . $this->data['BoundingBoxLeftLong'], 4);
					}

					// Check -90 to 90
					if (
								( ($this->data['BoundingBoxRightLat'] > 90) && ($this->data['BoundingBoxRightLat'] < -90) )
						||	( ($this->data['BoundingBoxLeftLat'] > 90) && ($this->data['BoundingBoxLeftLat'] < -90) )
					) {
						$this->addWarning("BoundingBoxLat", $this->data['BoundingBoxRightLat'] . " " . $this->data['BoundingBoxLeftLat'], 5);
					}

					// Length of 2 decimal degree check
/*					
					if ($this->getDecLen( $this->data['BoundingBoxRightLong'] ) < 2) $this->addWarning("BoundingBoxDecimalAcc", $this->data['BoundingBoxRightLong'], 6);
					if ($this->getDecLen( $this->data['BoundingBoxLeftLong'] ) < 2) $this->addWarning("BoundingBoxDecimalAcc", $this->data['BoundingBoxLeftLong'], 6);
					if ($this->getDecLen( $this->data['BoundingBoxRightLat'] ) < 2) $this->addWarning("BoundingBoxDecimalAcc", $this->data['BoundingBoxRightLat'], 6);
					if ($this->getDecLen( $this->data['BoundingBoxLeftLat'] ) < 2) $this->addWarning("BoundingBoxDecimalAcc", $this->data['BoundingBoxLeftLat'], 6);
*/					
			}
		}
		
		// Test ResourceURL for http:// prefix
		if ($this->data['ResourceURL'] != '') {
			if (!preg_match('/^http:\/\//', $this->data['ResourceURL'])) $this->addWarning("ResourceURL", $this->data['ResourceURL'], 7);
		}

//		print "<pre>";
//		print_r($this->data);
		return($this->error);
	}
	
	public function getRawXml() {
		return( $this->xml->outputMemory() );
	}

}

# UNUSED XML BUT MIGHT BE USED LATER DO NOT REMOVE
/*

					#	Not mentioned in the GBIF Extended Metadata Doc but seems sensible to keep this element -->
					#	PROCESSOR SEE IPR PURPOSE SECTION B55
					$this->xml->startElement('purpose');
						$this->xml->startElement('para');						
						$this->xml->endElement();
					$this->xml->endElement();

					# Methods used
					$this->xml->startElement('methods');
						$this->xml->startElement('methodStep');
							$this->xml->startElement('description');
								$this->xml->startElement('para');
//						
								$this->xml->endElement();
							$this->xml->endElement();
						$this->xml->endElement();
						$this->xml->startElement('qualityControl');
							$this->xml->startElement('description');
								$this->xml->startElement('para');
//						
								$this->xml->endElement();
							$this->xml->endElement();
						$this->xml->endElement(); # qualityControl
						$this->xml->startElement('sampling');
							$this->xml->startElement('studyExtent');
								$this->xml->startElement('description');
//						
								$this->xml->endElement();
							$this->xml->endElement();
							$this->xml->startElement('samplingDescription');
								$this->xml->startElement('para');
//						
								$this->xml->endElement();
							$this->xml->endElement();
						$this->xml->endElement(); # sampling
					$this->xml->endElement(); # methods

				#Methods
				# This is how MORPHO models it
				$this->xml->startElement('methods');
					$this->xml->startElement('methodStep');
						$this->xml->startElement('description');
							$this->xml->startElement('section');
								$this->xml->startElement('title');
//								
								$this->xml->endElement();
								$this->xml->startElement('para');
//								
								$this->xml->endElement();
							$this->xml->endElement();
						$this->xml->endElement();
						$this->xml->startElement('instrumentation');
//								
						$this->xml->endElement();
					$this->xml->endElement();
					
					$this->xml->startElement('sampling');
						$this->xml->startElement('studyExtent');
							$this->xml->startElement('description');
								$this->xml->startElement('para');
//							
								$this->xml->endElement();
							$this->xml->endElement();
						$this->xml->endElement();
						
						$this->xml->startElement('samplingDescription');
							$this->xml->startElement('para');
//							
							$this->xml->endElement();
						$this->xml->endElement();
					$this->xml->endElement();
				$this->xml->endElement();
*/


#----------------- Additions Author and Reference --------------------------
# Authors
/*
$authors = $this->get('authors');
$this->xml->startElement('Authors');
if(is_array($authors) && count($authors)) {
	foreach($authors as $author) {
		$this->xml->startElement('Author');
			$this->xml->startElement('individualName');
				$this->xml->startElement('givenName');
					# Requires at least 1 char
					$this->xml->text( ($author['Author.FirstName'] == "") ? "{FirstName}" : $author['Author.FirstName'] );
				$this->xml->endElement();
				$this->xml->startElement('surName');
					$this->xml->text( ($author['Author.LastName'] == "") ? "{LastName}" : $author['Author.LastName'] );
				$this->xml->endElement();
			$this->xml->endElement();
			$this->xml->startElement('organizationName');
				$this->xml->text( ($author['Author.Organisation'] == "") ? "{Organisation}" : $author['Author.Organisation'] );
			$this->xml->endElement();
			$this->xml->startElement('positionName');
# REQUIRED to have a valid string
$this->xml->text( ($this->get('Author.PositionName') == "") ? "{PositionName}" : $this->get('Author.PositionName') );
			$this->xml->endElement();
			$this->xml->startElement('address');
				$this->xml->startElement('city');
					$this->xml->text( ($author['Author.City'] == "") ? "{City}" : $author['Author.City'] );
				$this->xml->endElement();
				$this->xml->startElement('administrativeArea');
					$this->xml->text( ($author['Author.Province'] == "") ? "{Province}" : $author['Author.Province'] );
				$this->xml->endElement();
				$this->xml->startElement('postalCode');
					$this->xml->text( ($author['Author.PostalCode'] == "") ? "{PostalCode}" : $author['Author.PostalCode'] );
				$this->xml->endElement();
				$this->xml->startElement('country');
					$this->xml->text( ($author['Author.Country'] == "") ? "{Country}" : $author['Author.Country'] );
				$this->xml->endElement();
			$this->xml->endElement();
			$this->xml->startElement('phone');
				$this->xml->text( $author['Author.Phone'] );
			$this->xml->endElement();
			$this->xml->startElement('electronicMailAddress');
				$this->xml->text( $author['Author.Email'] );
			$this->xml->endElement();
			$this->xml->startElement('onlineUrl');
				$this->xml->text( $author['Author.Homepage'] );
			$this->xml->endElement();
		$this->xml->endElement();
	} # foreach
} # if array
$this->xml->endElement();

# References

$references = $this->get('references');
$this->xml->startElement('References');
if(is_array($references) && count($references)) {
	foreach($references as $reference) {
		$this->xml->startElement('Reference');
			$this->xml->text( $reference['Author.FirstName'] );
		$this->xml->endElement();
	} # foreach
} # if
$this->xml->endElement();

*/

#---------------------------------------------------------------------------

?>